<template>
  <div class="table-wrapper">
    <div class="table-header" v-if="header">{{ header }}</div>
    <div class="table-filter" v-if="filter">
      <slot name="filter">
        <Form ref="form" :form="filterForm" @submit="submitForm"></Form>
      </slot>
    </div>
    <slot name="operator"></slot>
    <slot name="selection">
      <div style="display: inline-block; margin-bottom: 15px" v-if="selection">
        <el-button size="small" plain type="success">
          已选：{{ multipleSelection.length }}个
        </el-button>
        <el-button size="small" type="warn" @click="clearSelection">
          清空所有
        </el-button>
      </div>
    </slot>
    <div :class="['table-body', header || footer ? 'pad' : '']">
      <el-table
        v-if="columns.length"
        ref="table"
        :size="size"
        :data="dataSource"
        :stripe="stripe"
        :border="border"
        :max-height="height"
        :default-expand-all="defaultExpandAll"
        v-loading="loading"
        height="100%"
        @sort-change="sortChange"
        @select-all="selectionChange"
        @select="selectionChange"
        style="min-height: 100%"
        :headerCellStyle="{
          textAlign: 'center',
          fontWeight: 400,
          background: '#66b1ff',
          color: 'white',
        }"
        :cell-style="{ textAlign: 'center' }"
      >
        <template v-for="(column, index) in columns">
          <el-table-column
            v-bind="column"
            v-if="column?.type == 'expand'"
            :key="index + column.prop"
          >
            <template slot-scope="props">
              <component
                :is="column.component || 'ExbandOrder'"
                :props="props"
              ></component>
            </template>
          </el-table-column>
          <el-table-column v-bind="column" :key="index + column.prop" v-else>
            <template #default="scope" v-if="column.action">
              <el-button
                v-for="(e, i) in column?.action"
                :key="i"
                :type="e.type"
                :style="e.style || {}"
                @click="$emit('action', e.options, scope.row)"
              >
                {{ e.text }}
              </el-button>
            </template>
            <template #default="scope" v-else-if="column.showTip">
              <el-popover
                :width="scope.column.width || scope.column.minWidth || 350"
                trigger="hover"
              >
                <template #reference>
                  <div class="tip-reference">
                    {{ scope.row[scope.column.property] }}
                  </div>
                </template>
                <template #default>
                  <div class="tip-content" @click="copyContent(scope)">
                    {{ scope.row[scope.column.property] }}
                  </div>
                </template>
              </el-popover>
            </template>
            <template #default="scope" v-else-if="column.render">
              <Render
                :scope="scope"
                :column="column"
                :pageSize="pageSize"
                :page-sizes="pageSizes"
                :currentPage="currentPage"
                @handleRender="
                  (arg, params) => $emit('action', arg, scope.row, params)
                "
              />
            </template>
          </el-table-column>
        </template>
      </el-table>
    </div>
    <slot name="pagination">
      <div class="table-pagination" v-if="pagination">
        <span class="pagination-total"> 共 {{ total }} 条 </span>
        <el-pagination
          :total="total"
          @size-change="sizeChange"
          @current-change="currentChange"
          :pageSize="pageSize"
          :currentPage="currentPage"
          background
          layout="sizes,prev, pager, next, jumper"
        ></el-pagination>
      </div>
    </slot>
    <slot name="footer">
      <div class="table-footer" v-if="footer">{{ footer }}</div>
    </slot>
  </div>
</template>

<script>
import Render from '@/assets/js/Render.js'
import { copy } from 'iclipboard'
import _ from 'lodash'

export default {
  name: 'Table',
  components: {
    Render,
  },
  props: {
    filter: {
      type: Boolean,
      default: false,
    },
    total: {
      type: Number,
      default: 0,
    },
    header: {
      type: String,
      default: '',
    },
    footer: {
      type: String,
      default: '',
    },
    loading: {
      type: Boolean,
      default: false,
    },
    defaultExpandAll: {
      type: Boolean,
      default: false,
    },
    stripe: {
      type: Boolean,
      default: false,
    },
    border: {
      type: Boolean,
      default: true,
    },
    pagination: {
      type: Boolean,
      default: true,
    },
    size: {
      type: String,
      default: 'small',
    },
    height: {
      type: String,
      default: '550px',
    },
    pageSizes: {
      type: Array,
      default: () => [5, 10, 20, 50, 100],
    },
    selection: {
      type: Boolean,
      default: false,
    },
    form: {
      type: Object,
      default: () => ({
        search: {
          tag: 'el-input',
          label: '查询条件',
          value: '',
          props: {
            clearable: true,
            placeholder: '请搜索...',
          },
        },
        date: {
          tag: 'el-date-picker',
          value: [],
          props: {
            rangeSeparator: '至',
            startPlaceholder: '开始时间',
            endPlaceholder: '结束时间',
            type: 'datetimerange',
          },
        },
      }),
    },
    dataSource: {
      type: Array,
      default: () => [],
    },
    columns: {
      type: Array,
      default: () => [
        { prop: 'name', label: 'Name', width: '180' },
        { prop: 'date', label: 'date' },
        { prop: 'address', label: 'Address' },
        { prop: 'action', label: 'Address', action: [] },
      ],
    },
  },
  data() {
    return {
      filterForm: JSON.parse(JSON.stringify(this.form)),
      pageSize: 20,
      currentPage: 1,
      formValue: {},
      multipleSelection: [],
    }
  },
  computed: {
    selectMap() {
      const res = {}
      const arr = this.multipleSelection
      arr.forEach((e) => {
        res[e.id] = true
      })
      return res
    },
  },
  watch: {
    dataSource: {
      immediate: true,
      deep: true,
      handler() {
        this.initSelector()
      },
    },
  },
  mounted() {
    // console.log('mounted233')
    this.initTable()
  },
  methods: {
    initTable() {
      if (this.$refs.form) this.$refs.form.submit()
      else this.fetchTable()
    },
    initSelector() {
      setTimeout(() => {
        const { selection, selectMap, dataSource } = this
        const ref = this.$refs.table
        if (dataSource.length && selection && ref) {
          const rows = dataSource.filter((e) => selectMap[e.id])
          if (rows.length)
            rows.forEach((row) => {
              ref.toggleRowSelection(row)
            })
        }
      }, 2)
    },
    copyContent: _.throttle(function (scope) {
      if (copy(scope.row[scope.column.property]))
        this.$message.success('复制成功')
      else this.$message.error('复制失败')
    }, 1000),
    selectionChange(rows, row) {
      if (rows.length) {
        rows = rows.filter((e) => !this.selectMap[e.id])
        this.multipleSelection = [...rows, ...this.multipleSelection]
      } else {
        let datas = this.dataSource
        if (row) datas = [row]
        const map = {}
        datas.forEach((e) => {
          map[e.id] = true
        })
        this.multipleSelection = this.multipleSelection.filter(
          (e) => !map[e.id]
        )
        this.initSelector()
      }
    },
    clearSelection() {
      this.multipleSelection = []
      const ref = this.$refs.table
      ref && ref.clearSelection()
    },
    sortChange(props) {
      this.$emit('sortChange', props, this)
    },
    submitForm(form = {}) {
      this.currentPage = 1
      this.formValue = form
      this.fetchTable(form)
    },
    sizeChange(size) {
      this.pageSize = size
      this.currentPage = 1
      this.fetchTable(this.formValue)
    },
    currentChange(page) {
      this.currentPage = page
      this.fetchTable(this.formValue)
    },
    fetchTable(form = this.formValue) {
      this.formValue = {
        ...form,
        pageNumber: this.currentPage,
        pageSize: this.pageSize,
      }
      this.$emit('fetchTable', this.formValue)
    },
  },
}
</script>

<style lang="less" scoped>
.table-wrapper {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;

  .table-header {
    padding-left: 14px;
    line-height: 40px;
    font-size: 12px;
    border-bottom: 1px solid #e2e8f0;
    background-color: #f9fafb;
    color: #1e293b;
  }

  .table-filter {
    :deep(.el-form--inline) {
      padding-bottom: 5px;

      .el-form-item {
        margin-bottom: 8px;
      }
    }
  }

  .operator-wrap {
    padding-bottom: 15px;
  }

  .table-body {
    flex: 1;
    overflow: hidden;
    background-color: #ffffff;

    &.pad {
      padding: 12px 20px 20px;
    }
  }

  .table-pagination {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    margin: 10px 5px;

    .pagination-total {
      color: #606266;
      font-size: 12px;
    }
  }

  .table-footer {
    padding-left: 14px;
    line-height: 40px;
    font-size: 12px;
    border-top: 1px solid #e2e8f0;
    background-color: #f9fafb;
    color: #1e293b;
  }

  :deep(tbody td) {
    background-color: white;
  }

  :deep(thead th) {
    font-weight: 500;
    background: #f9fafb;
    color: #6b7280;
  }

  :deep(tbody .cell) {
    color: #374151;
    padding-left: 7px;
    padding-right: 7px;
  }
}
</style>
